﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Microsoft.Xna.Framework.Input;
using SpaceAdventureLib.Universe.Weapons;
using SpaceAdventureLib.Input;

namespace SpaceAdventureLib.Universe.Units
{
    [Serializable]
    public class Player : Fighter
    {

        #region "Properties"

        private Cursor cursor = null;
        public Cursor Cursor
        {
            get { return this.cursor; }
            set { this.cursor = value; }
        }

        #endregion

        #region "Variables"
        

        #endregion

        #region "Constructor"

        public Player(Space space)
            : base(space)
        {

            this.cursor = new Cursor();

            this.ModelName = "Units\\Player\\Ship";

            this.Mass = 1.0f;
            this.ThrustForce = 24000.0f;
            this.DragFactor = 0.97f;

            this.RotationVelocity = new Vector3(1.5f);

            this.MoveTo(new Vector3(100));

        }
        
        #endregion

        #region "Methods"

        public override void FinaliseInitialization()
        {

            base.FinaliseInitialization();

            Weapon weapon = new Gun(this);
            this.Weapons.Add(weapon);
            this.ActiveWeapon = weapon;
            weapon.MoveTo(this.Location);
            weapon.Reload();

        }

        public override List<TNCGameEngine.Content.AssetToLoad> GetAssetsToLoad()
        {
            return base.GetAssetsToLoad();
        }

        public override void LoadContent(TNCGameEngine.Content.ContentLoader loader)
        {
            base.LoadContent(loader);
            this.cursor.LoadContent(loader);
        }

        public override void UnloadContent(TNCGameEngine.Content.SharedContentManager content)
        {
            base.UnloadContent(content);
            this.cursor.UnloadContent(content);
        }

        public override void Update(GameTime gameTime)
        {

            KeyboardState keyboardState = Keyboard.GetState();
            MouseState mouseState = Mouse.GetState();

            float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

            this.RotationVelocity += this.RotationAcceleration * dt;
            if (keyboardState.IsKeyDown(Keys.D))
            {
                this.Rotate(new Vector3(-this.RotationVelocity.X * dt, 0, 0));
            }
            else if (keyboardState.IsKeyDown(Keys.A))
            {
                this.Rotate(new Vector3(this.RotationVelocity.X * dt, 0, 0));
            }

            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                //Plane plane = new Plane(this.Forward, this.Location, this.Right);
                Plane plane = new Plane(Vector3.Forward, Vector3.Zero, Vector3.Right);
                Ray ray = this.cursor.CalculateCursorRay(this.Space.GraphicsDevice, this.Space.MainCamera.Projection, this.Space.MainCamera.View);
                float? dist = ray.Intersects(plane);
                if (dist.HasValue)
                {
                    this.ActiveWeapon.Shoot(ray.Position + dist.Value * ray.Direction);
                }
            }
            else if (mouseState.LeftButton == ButtonState.Released)
            {
                this.ActiveWeapon.StopShooting();
            }

            foreach (Weapon w in this.Weapons)
            {
                w.Update(gameTime);
            }

            this.cursor.Update(gameTime);

            this.UpdateDirections();
            this.UpdateWorldMatrix();
            
            float thrustAmount = keyboardState.IsKeyDown(Keys.W) ? 1.0f : 0.0f;
            Vector3 force = this.Forward * thrustAmount * this.ThrustForce;

            this.Acceleration = force / this.Mass;
            this.Velocity += this.Acceleration * dt;
            this.Velocity *= this.DragFactor;
            this.Move(this.Velocity * dt);

        }

        public void Draw2D(SpriteBatch spriteBatch)
        {            
            this.cursor.Draw(spriteBatch);
        }

        #endregion

    }
}
